Upon changing to a new instruction set architecture (ISA), it is desirable to continue to be able to support legacy code that was compiled on the old architecture. Thus, the problem is that both the legacy code and the new native code that is compiled specifically for the new architecture must be supported on the new ISA The prior art would typically use binary translation to convert the old code into new code. Binary translation is the process of directly translating object code compiled for the legacy instruction set architecture object code for the native architecture. This allows software transition between two dissimilar ISAs.
However, there are situations when a mixture of legacy code and native code needs to be run, and a binary translation itself will not efficiently handle the two sets of code. Thus, a mechanism for mode switching between the two sets of code is required.
One prior art mechanism used switch stubs. The users had to manually create these switch stubs statically or when the program was developed. The stubs would be positioned between the legacy code and the native code, and when the application wanted to make a mode transition or a switch from emulating the old legacy code to executing the new native code, the application would explicitly transfer control via one of these switch stubs. A mode transition is where the flow of execution in the program switches from legacy code to native code, or vice versa. For the remainder of this application the legacy code will be referred to as compatibility mode code or CM, and the native mode code will be referred to a native mode code or NM.
Another prior art mechanism for performing mode switches used a universal procedure pointer (UPP), which are dynamically created. Thus, before the application makes a call to a routine or procedure that is written in CM, the application would explicitly create a universal procedure pointer for that procedure. The application would take the address of the CM code, and pass it to a system routine that would create a UPP pointer for the CM code. In addition to the address, the application would have to pass additional information about the specific routine or procedure, specifically, a parameter profile. The profile defines the kinds of arguments the procedure call is expecting, so that the universal procedure pointer is built to pass it through a dynamically created stub that would automatically reformat the arguments. This mechanism works similarly in each direction, i.e. from CM to NM, and from NM to CM.
Note that this mechanism is not transparent, if a mode switch is required, it is explicitly made, i.e. the user had to know it was going to be done when writing the program. The application would pass the information about the parameter profile to a stub builder, which is similar to a compiler. The stub builder would take the information and generate the switch stubs as assembly code and then those switch stubs would get compiled into the program. The universal procedure pointer which would point to a little stub.
A serious problem with the prior art mechanisms is that they are not transparent. The user must explicitly know about all the transitions that might be made between compatibility mode and native mode, and prepare for them ahead of time, by either building the switch stubs or creating the code that would dynamically create the UPP. Moreover, the user must be concerned about parameters, because the parameter passing conventions are different between the compatibility mode and native mode procedures. Thus, whenever a procedure call is made that requires a mode switch, either from CM to NM or from NM to CM, the application would have to bundle all of the arguments that are to be passed, and reformat them to match the conventions of the procedure being called. Additional information about the procedure that is being called must be maintained in order to build the switch stub or the UPP. The parameter reformatting or marshalling takes place during run time. Consequently, system performance is adversely affected as well.
Therefore, there is a need in the art to have a mechanism that would allow legacy code or CM which is compiled for an old architecture to be linked with native code or NM which is compiled for the new architecture with no additional effort.